#pragma once
#include <iostream>
#include <cstring>
#include <string>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <functional>
#include "Log.hpp"
#include "InetAddr.hpp"

using namespace LogModule;

const int Numdefault = -1;
using fun_c = std::function<void(int sockfd, const std::string& , InetAddr&)>;

class UdpServe
{
public:
    UdpServe(uint16_t port,fun_c func)//创建时，接收ip和端口，
        :_sockfd(Numdefault)
        ,_func(func)
        //,_ip(ip)
        ,_port(port)
        ,_isrunning(false)
    {
 
    }

    void Init()
    {
        //1.创建套接字
        _sockfd = socket(AF_INET,SOCK_DGRAM,0);//网络通信，通信协议 UDP
        if(_sockfd < 0)
        {
            LOG(LogLevel::FATAL) << "socket error";
            exit(1);
        }
        //LOG(LogLevel::DEBUG) << "socket success";

        //2 绑定socket信息，ip 和 端口
        //2.1 填充 sockadd_in结构体 
        //struct sockaddr_in local;
        //bzero(&local,sizeof(local));//初始化结构体
        //local.sin_family = AF_INET;//网络通信
        //local.sin_port = htons(_port);//主机序列转网络序列，小端转大端，大端不变
        //1.IP转成4字节  2.4字节转成网络序列 -> in_addr_t_inet_addr(const char* cp)
        //local.sin_addr.s_addr = inet_addr(_ip.c_str());//将点分十进制风格的ip 转为 4字节类型风格的ip
        //local.sin_addr.s_addr = INADDR_ANY;//接收当前服务器下包含的任何ip地址

        InetAddr local(_port);

        int n = bind(_sockfd,(struct sockaddr*)&(local.NetAddr()),sizeof(local));
        if(n < 0)
        {
            LOG(LogLevel::FATAL) << "bind error";
            exit(2);
        }
        LOG(LogLevel::DEBUG) << "bind success, sockfd : " << _sockfd ;

    }

    void start()
    {
        _isrunning = true;
        while(_isrunning)
        {
            char buffer[1024];
            struct sockaddr_in peer;//创建一个本地的sockaddr_in 结构体 接收远端客户端信息
            socklen_t len = sizeof(peer);
            

            ssize_t s = recvfrom(_sockfd,buffer,sizeof(buffer)-1,0,(sockaddr*)&peer,&len);
            
            if(s > 0)
            {
                InetAddr client(peer);//格式转换交给另一个类来处理，UdpServer 只需要通信即可
                buffer[s] = 0;
                _func(_sockfd,buffer,client);//buffer是一个临时变量，无法传递给一个非const的左值引用变量
                
            }

        }
    }

    ~UdpServe()
    {
        
    }
private:
    int _sockfd;
    uint16_t _port;
    bool _isrunning;
    //std::string _ip;
    fun_c _func;
};